home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / networke / civ-0.000 / civ-0 / civ-0.3 / src / server.cc < prev    next >
C/C++ Source or Header  |  1995-11-17  |  5KB  |  223 lines

  1. #ifndef MS_WIN
  2. #include <sys/types.h>
  3. #include <netdb.h>
  4. #include <netinet/in.h>
  5. #include <sys/socket.h>
  6. #include <unistd.h>
  7. #else
  8. #include <winsock.h>
  9. #endif
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12.  
  13. #include "defs.h"
  14. #include "server.h"
  15. #include "graph.h"
  16. #include "MsgQ.h"
  17. #include "net.h"
  18.  
  19. struct PlayerInfo
  20. {
  21.   char *name;
  22.   int fd;
  23.   int route;
  24.   int id;
  25. };
  26.  
  27. static PlayerInfo *playerTable;
  28. static int connSock;
  29. static int leftToConnect;
  30.  
  31. const int ConnectPort = 7123;
  32.  
  33. // clients use this socket to communicate with the server
  34. int sock;
  35.  
  36. // q is NULL
  37. static void NewConnection(MsgQ *q, int fd, int info)
  38. {
  39.   static int currPlayer = 1;
  40.   struct sockaddr_in sock_in;
  41.   int tmp, new_sock;
  42.  
  43.   tmp = sizeof(sock_in);
  44.   new_sock = accept(fd, (struct sockaddr *)&sock_in, &tmp);
  45.   if (new_sock < 0) return;
  46.   if (currPlayer >= numPlayers) {
  47. #ifdef MS_WIN
  48.     closesocket(new_sock);
  49. #else
  50.     close(new_sock);
  51. #endif
  52.     return;
  53.   }
  54.  
  55.   int set = 1;
  56.   setsockopt(new_sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&set, sizeof(set));
  57.  
  58.   playerTable[currPlayer].fd = new_sock;
  59.   playerTable[currPlayer].route = -1;
  60.   playerTable[currPlayer].id = currPlayer;
  61.   screen->AddReadNotify(new_sock, ServerGotData, currPlayer);
  62.   ++currPlayer;
  63. }
  64.  
  65. void InitServer()
  66. {
  67.   playerTable = new PlayerInfo[numPlayers];
  68.   playerTable[0].name = myName;
  69.   playerTable[0].fd = -1;
  70.   playerTable[0].route = -1;
  71.   playerTable[0].id = 0;
  72.   leftToConnect = numPlayers-1;
  73.  
  74.   struct sockaddr_in sock_in;
  75.   int val;
  76.  
  77.   sock_in.sin_addr.s_addr = htonl(INADDR_ANY);
  78.   sock_in.sin_port = htons(ConnectPort);
  79.   sock_in.sin_family = AF_INET;
  80.  
  81.   if ((connSock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
  82.     fprintf(stderr, "socket failed\n");
  83.     exit(1);
  84.   }
  85.   val = 1;
  86.   if (setsockopt(connSock, SOL_SOCKET, SO_REUSEADDR, (char *)&val,
  87.          sizeof(val)) < 0) {
  88.     fprintf(stderr, "setsockopt failed\n");
  89.     exit(1);
  90.   }
  91.   if (bind(connSock, (struct sockaddr *)&sock_in, sizeof(sock_in)) < 0) {
  92.     fprintf(stderr, "bind failed\n");
  93.     exit(1);
  94.   }
  95.   if (listen(connSock, 5) < 0) {
  96.     fprintf(stderr, "listen failed\n");
  97.     exit(1);
  98.   }
  99.  
  100.   screen->AddReadNotify(connSock, NewConnection, 0, 0);
  101. }
  102.  
  103. void ServerGotData(MsgQ *q, int fd, int player)
  104. {
  105.   static int waitingOnSynch = 0;
  106.   long cmd, arg;
  107.   int i;
  108.   if (!q->IsCmd(cmd, arg)) {
  109.     if (playerTable[player].route == -1) { // send to everyone
  110.       MsgQ *copy = NULL;
  111.       int sendsLeft = numPlayers-1;
  112.       if (player != 0) {
  113.     --sendsLeft;
  114.     copy = q->Copy();
  115.       }
  116.       if (sendsLeft == 0)
  117.     delete q;
  118.       for (i = 1; i < numPlayers; ++i)
  119.     if (i != player) {
  120.       --sendsLeft;
  121.       if (sendsLeft >= 1)
  122.         NonDestructiveSendQ(playerTable[i].fd, q);
  123.       else
  124.         SendQ(playerTable[i].fd, q);
  125.     }
  126.       if (player != 0)
  127.     HandleMessage(copy, -1, 0);
  128.       return;
  129.     }
  130.     // send to specific player
  131.     if (playerTable[player].route == 0)
  132.       HandleMessage(q, -1, 0);
  133.     else {
  134.       for (int i = 0;;++i)
  135.     if (playerTable[i].id == playerTable[player].route) {
  136.       SendQ(playerTable[i].fd, q);
  137.       break;
  138.     }
  139.     }
  140.     return;
  141.   }
  142.   // the message is a command
  143.   MsgQ *send;
  144.   switch (cmd) {
  145.   case GET_PLAYER_INFO:
  146.     delete q;
  147.     send = new MsgQ;
  148.     *send << "player_info";
  149.     *send << numPlayers;
  150.     for (i = 0; i < numPlayers; ++i)
  151.       *send << playerTable[i].name;
  152.     if (player == 0)
  153.       HandleMessage(send, -1, 0);
  154.     else
  155.       SendQ(playerTable[player].fd, send);
  156.     return;
  157.   case CHANGE_ROUTE:
  158.     delete q;
  159.     playerTable[player].route = arg;
  160.     return;
  161.   case SYNCH:
  162.     delete q;
  163.     if (waitingOnSynch == 0) // initiated synchronise
  164.       waitingOnSynch = numPlayers-1;
  165.     else {
  166.       --waitingOnSynch;
  167.       if (waitingOnSynch == 0) {
  168.     send = new MsgQ;
  169.     *send << "synch";
  170.     for (i = 1; i < numPlayers; ++i)
  171.       if (i == numPlayers-1)
  172.         SendQ(playerTable[i].fd, send);
  173.       else
  174.         NonDestructiveSendQ(playerTable[i].fd, send);
  175.     send = new MsgQ;
  176.     *send << "synch";
  177.     HandleMessage(send, -1, 0);
  178.       }
  179.     }
  180.     return;
  181.   case CONNECT:
  182.     *q >> playerTable[player].name;
  183.     delete q;
  184.     if (--leftToConnect <= 0) {
  185.       send = new MsgQ;
  186.       *send << "send_map";
  187.       HandleMessage(send, -1, 0);
  188.     }
  189.     return;
  190.   case RECONNECT:
  191.     *q >> playerTable[player].name;
  192.     delete q;
  193.     playerTable[player].id = arg;
  194.     --leftToConnect;
  195.     return;
  196.   }
  197.   delete q;
  198.   return;
  199. }
  200.  
  201. // client calls this to connect to us
  202. void ConnectServer(char *server)
  203. {
  204.   struct sockaddr_in addr;
  205.   struct hostent FAR *host;
  206.  
  207.   addr.sin_port = htons(ConnectPort);
  208.   host = gethostbyname(server);
  209.   if (host == NULL) {
  210.     exit(1);
  211.   }
  212.   addr.sin_addr = *(struct in_addr *)host->h_addr;
  213.  
  214.   sock = socket(PF_INET, SOCK_STREAM, 0);
  215.   if (sock < 0) {
  216.     exit(1);
  217.   }
  218.   addr.sin_family = AF_INET;
  219.   if (connect(sock, (sockaddr *)&addr, sizeof(addr)) < 0) {
  220.     exit(1);
  221.   }
  222. }
  223.